/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.uca.dss.curso1011.grupo9.interfazExtendido;

import java.util.ArrayList;
import org.uca.dss.curso1011.grupo9.interfaz.*;
import java.util.LinkedList;
import java.lang.RuntimeException;
import java.util.Set;
import java.util.HashSet;
import org.joda.time.LocalDate;
import java.util.Map;
import java.util.Random;
import org.joda.time.LocalTime;
import java.util.List;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;

/**
 *
 * @author dmolina
 */
public class InterfazExtendidoTestCompras extends InterfazExtendidoTest {

    /**
     * Comprueba que una reserva reduzca los asientos libres 
     * para ese día y fecha, y
     * no modifica ni otro día ni otra hora cualquiera
     */
    @Test
    public void testUnaReserva() {
        List<LocalTime> horasPosibles = getHorasPosibles();
        LocalTime hora, hora2;

        hora = getHoraAleatoria(horasPosibles);

        do {
            hora2 = getHoraAleatoria(horasPosibles);
        } while (hora2.equals(hora));

        List<Itinerario> itinerarios1 = listado.getItinerariosEntre(origen, destino, hoy, hora, null);
        List<Itinerario> itinerarios2 = listado.getItinerariosEntre(origen, destino, hoy, hora2, null);

        List<Integer> libresAntes = new ArrayList<Integer>();
        List<Integer> libresOtraHoraAntes = new ArrayList<Integer>();
        for (Itinerario it : itinerarios1)
            libresAntes.add(compras.asientosLibres(hoy, it));

        for (Itinerario it : itinerarios2)
            libresOtraHoraAntes.add(compras.asientosLibres(hoy, it));

        // Hay al menos un elemento
        assertNotSame(itinerarios1.size(), 0);

        compras.reservaAsiento(itinerarios1.get(0), hoy);

        List<Integer> libresDespues = new ArrayList<Integer>();
        List<Integer> libresOtraHoraDespues = new ArrayList<Integer>();
        List<Integer> libresOtroDia = new ArrayList<Integer>();
        
        for (Itinerario it : itinerarios1)
            libresDespues.add(compras.asientosLibres(hoy, it));

        for (Itinerario it : itinerarios2)
            libresOtraHoraDespues.add(compras.asientosLibres(hoy, it));

        for (Itinerario it : itinerarios1)
            libresOtroDia.add(compras.asientosLibres(hoy.plusDays(1), it));


        libresDespues.set(0, libresDespues.get(0) + 1);
        assertEquals(libresAntes.size(), libresDespues.size());
        for (Integer i = 0; i < libresAntes.size(); i++)
            assertEquals(libresAntes.get(i), libresDespues.get(i));

        assertEquals(libresAntes.size(), libresOtroDia.size());
        for (Integer i = 0; i < libresAntes.size(); i++)
            assertEquals(libresAntes.get(i), libresOtroDia.get(i));

        assertEquals(libresOtraHoraAntes.size(), libresOtraHoraDespues.size());
        for (Integer i = 0; i < libresOtraHoraAntes.size(); i++)
            assertEquals(libresOtraHoraAntes.get(i), libresOtraHoraDespues.get(i));
    }

    /**
     * Comprueba que asientos libres se reduzca al reservar cada vez
     */
    @Test
    public void testReservarReduceAsientosLibres() {
        List<LocalTime> horas = getHorasPosibles();
        LocalTime hora = getHoraAleatoria(horas);

        List<Itinerario> itinerarios = listado.getItinerariosEntre(origen, destino, hoy, hora, null);

        List<Integer> libres = new ArrayList<Integer>();
        for (Itinerario it : itinerarios)
            libres.add(compras.asientosLibres(hoy, it));


        //int libres = compras.asientosLibres(origen, destino, hoy, hora);
        List<Integer> reservados = new ArrayList<Integer>();

        for (Integer i = 0; i < itinerarios.size(); i++)
        {
            reservados.add(0);
            while(compras.asientosLibres(hoy, itinerarios.get(i)) > 0)
            {
                compras.reservaAsiento(itinerarios.get(i), hoy);
                reservados.set(i, reservados.get(i) + 1);
            }
        }

        assertEquals(libres.size(), reservados.size());
        for (Integer i = 0; i < libres.size(); i++)
        {
            assertSame("No permite reservar tantos asientos como libres", libres.get(i), reservados.get(i));
        }
    }

    /**
     * Comprueba que se puede cancelar una reservada
     */
    @Test
     public void testReservaYCancela() {
        List<LocalTime> horas = getHorasPosibles();
        LocalTime hora = getHoraAleatoria(horas);

        List<Itinerario> itinerarios = listado.getItinerariosEntre(origen, destino, hoy, hora, null);

        List<Integer> libresAntes = new ArrayList<Integer>();
        for (Itinerario it : itinerarios)
            libresAntes.add(compras.asientosLibres(hoy, it));

        // Hay al menos un elemento
        assertNotSame(itinerarios.size(), 0);

        List<ReservaTrayecto> rt = compras.reservaAsiento(itinerarios.get(0), hoy);

        List<Integer> libresDespues = new ArrayList<Integer>();

        for (Itinerario it : itinerarios)
            libresDespues.add(compras.asientosLibres(hoy, it));

        compras.cancelaReserva(rt);

        List<Integer> libresTrasCancelar = new ArrayList<Integer>();

        for (Itinerario it : itinerarios)
            libresTrasCancelar.add(compras.asientosLibres(hoy, it));

        libresDespues.set(0, libresDespues.get(0) + 1);
        assertEquals(libresAntes.size(), libresDespues.size());
        for (Integer i = 0; i < libresAntes.size(); i++)
            assertEquals(libresAntes.get(i), libresDespues.get(i));

        assertEquals(libresAntes.size(), libresTrasCancelar.size());
        for (Integer i = 0; i < libresAntes.size(); i++)
            assertEquals(libresAntes.get(i), libresTrasCancelar.get(i));
     }

     @Test(expected=RuntimeException.class)
     public void testCancelaSinReservar() {
         ReservaTrayecto rt = new ReservaTrayecto(null, null, -1, null);
         compras.cancelaReserva(rt);
     }

     @Test
     public void testReservaYCancelaOtra() {
         List<LocalTime> horas = getHorasPosibles();
         LocalTime hora = getHoraAleatoria(horas);
         List<Itinerario> itinerarios = listado.getItinerariosEntre(origen, destino, hoy, hora, null);
         assertNotSame(itinerarios.size(), 0);
         List<ReservaTrayecto> rt = compras.reservaAsiento(itinerarios.get(0), hoy);
         ReservaTrayecto rtfalso = new ReservaTrayecto(rt.get(0).getTrayecto(), hoy, rt.get(0).getNumeroAsiento(), rt.get(0).getCodigoReserva()+"NULO");
         try {
            compras.cancelaReserva(rtfalso);
            fail("Canceló una reserva con falso código");
         } catch (RuntimeException e) { }
         
     }

     @Test
     public void testLLenaYCancela() {
        List<LocalTime> horas = getHorasPosibles();

        for (LocalTime hora : horas) {
            System.out.println("-------\n" +hora);

            List<Itinerario> itinerarios = listado.getItinerariosEntre(origen, destino, hoy, hora, null);

            Integer libresInicialmente;
            assertNotSame(itinerarios.size(), 0);
            Itinerario it = itinerarios.get(0);
            libresInicialmente = compras.asientosLibres(hoy, it);

            List<List<ReservaTrayecto>> llrt = new ArrayList<List<ReservaTrayecto>>();

            while(compras.asientosLibres(hoy, it) > 0)
                llrt.add(compras.reservaAsiento(it, hoy));

            int cancelado = 0;
            for (List<ReservaTrayecto> lrt : llrt)
            {
                compras.cancelaReserva(lrt);
                System.out.println("Cancelado : " +cancelado);
                cancelado++;
            }

            int libresFinal = compras.asientosLibres(hoy, it);
            assertSame(libresInicialmente, libresFinal);
                System.out.println("-------");
     }

    }
}